package DependencyModeling;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

public class DataSet {
	private ArrayList<ArrayList<DataItem>> permutationList;
	public ArrayList<String> possibleItems;
	public ArrayList<ArrayList<DataItem>> items;
	public int maxLevel;
	public int TotalItems;
	
	public DataSet(ArrayList<DataItem> dataItems)
	{ 
		SortedSet<DataItem> newItems = new TreeSet<DataItem>();
		for(DataItem itm : dataItems)
		{
			newItems.add(itm);
		}
		
		int currentSize = 1;
		maxLevel = newItems.last().size;
		this.TotalItems = newItems.size();
		this.TotalItems = dataItems.size();
		
		this.items = new ArrayList<ArrayList<DataItem>>(maxLevel);
		for (int i = 0; i < maxLevel; i ++)
			items.add(new ArrayList<DataItem>());
		
		Iterator<DataItem> it = newItems.iterator();
		
		for (int i = 0; i < this.TotalItems; i++)
		{
			DataItem current = it.next();
			if (current.items.size() > currentSize)
				currentSize = current.items.size();
			this.items.get(currentSize-1).add(current);
		}
		
		ArrayList<String> values = new ArrayList<String>();
		for (int i = 0; i < this.items.size(); i++)
		{
			ArrayList<DataItem> currentLevel = this.items.get(i);
			for (int j = 0; j < currentLevel.size(); j++)
			{
				DataItem currentItem = currentLevel.get(j);
				for (String value : currentItem.items)
				{
					if (!values.contains(value))
						values.add(value);
				}
			}
		}
		possibleItems = values;
	}
	
	public void Trim(DataItem trimmer)
	{
		for (int i = trimmer.size; i<maxLevel; i++)
		{
			ArrayList<DataItem> currentLevel = items.get(i);
			for (DataItem item : currentLevel)
			{
				if (item.IsSuperSetOf(trimmer))
				{
					item.SetTrimmed(true);
				}
			}
			currentLevel = permutationList.get(i);
			for (DataItem item : currentLevel)
			{
				if (item.IsSuperSetOf(trimmer))
				{
					item.SetTrimmed(true);
				}
			}
		}
	}
	
	public void ComputeSupport(double SupportLevel)
	{
		for (int i = 0; i < permutationList.size(); i++)
		{
			ArrayList<DataItem> currentLevel = permutationList.get(i);
			for (int j = 0; j < currentLevel.size(); j++)
			{
				DataItem itm = currentLevel.get(j);
				if (!itm.Trimmed)
				{
					itm.SetSupport(GetSupport(itm));
					if (itm.support < SupportLevel)
						Trim(itm);
				}
			}
		}
	}
	
	private Double GetSupport(DataItem dataItem) 
	{
		int count = 0;
		for (int i = dataItem.size; i <= maxLevel; i++)
		{
			ArrayList<DataItem> level = items.get(i-1);
			for (DataItem itm : level)
			{
				if (itm.IsSuperSetOf(dataItem))
					count++;
			}
		}
		return (double)count/(double)TotalItems;
	}

	public void BuildPermutation(ArrayList<String> items)
	{
		permutationList = new ArrayList<ArrayList<DataItem>>();
		permutationList.ensureCapacity(maxLevel+1);
		for (int i = 0; i < maxLevel+1; i++)
			permutationList.add(new ArrayList<DataItem>());
		RecursePermutation(new ArrayList<String>(), items);
	}
	
	private void RecursePermutation(ArrayList<String> prefix, List<String> rest)
	{
		if (prefix.size() > 0)
			permutationList.get(prefix.size()).add(new DataItem(prefix));
		for (int i = 0; i < rest.size(); i++)
		{
			ArrayList<String> newList = new ArrayList<String>(prefix);
			newList.add(rest.get(i));
			RecursePermutation(newList, rest.subList(i+1, rest.size()));
		}
	}
	
	public void PrintPermutations(Boolean printSupport)
	{
		for(int i = 0; i < permutationList.size(); i++)
		{
			ArrayList<DataItem> currentLevel = permutationList.get(i);
			if (currentLevel.size() > 0)
			{
				for (DataItem itm : currentLevel)
				{
					System.out.print(itm.size + ":");
					for (String str : itm.items)
						System.out.print(str + "-");
					if (printSupport)
						System.out.print(itm.support);
					System.out.println();
				}
			}
			else
				System.out.println(i + ":");
		}
	}
	
	public void PrintDataSet()
	{
		for(int i = 0; i < items.size(); i++)
		{
			ArrayList<DataItem> currentLevel = items.get(i);
			if (currentLevel.size() > 0)
			{
				for (DataItem itm : currentLevel)
				{
					if (!itm.Trimmed)
					{
						System.out.print(itm.size+":");
						for (String str : itm.items)
							System.out.print(str + "-");
						System.out.println();
					}
				}
			}
			else
				System.out.println(i + ":");
		}
	}
}
